package org.truenewx.tnxjee.webmvc.util;

import java.util.Locale;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.RequestContextUtils;
import org.truenewx.tnxjee.core.Strings;
import org.truenewx.tnxjee.core.util.ArrayUtil;
import org.truenewx.tnxjee.core.util.NetUtil;
import org.truenewx.tnxjee.core.util.SpringUtil;
import org.truenewx.tnxjee.web.context.SpringWebContext;
import org.truenewx.tnxjee.webmvc.bind.annotation.ResponseStream;

/**
 * Spring Web Mvc工具类
 *
 * @author jianglei
 */
public class SpringWebMvcUtil {

    /**
     * 直接重定向的视图名称前缀
     */
    public static final String REDIRECT_VIEW_NAME_PREFIX = "redirect:";

    private SpringWebMvcUtil() {
    }

    /**
     * 获取web项目应用范围内的ApplicationContext实例
     *
     * @param request HTTP请求
     * @return ApplicationContext实例
     */
    public static ApplicationContext getApplicationContext(HttpServletRequest request) {
        try {
            return RequestContextUtils.findWebApplicationContext(request);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取web项目应用范围内的ApplicationContext实例
     *
     * @return ApplicationContext实例
     */
    public static ApplicationContext getApplicationContext() {
        return getApplicationContext(SpringWebContext.getRequest());
    }

    public static ApplicationContext getApplicationContext(ServletContext servletContext) {
        return WebApplicationContextUtils.getWebApplicationContext(servletContext);
    }

    public static Environment getEnvironment() {
        return getApplicationContext().getEnvironment();
    }

    public static String getApplicationName(HttpServletRequest request) {
        ApplicationContext context = getApplicationContext(request);
        if (context != null) {
            return SpringUtil.getApplicationName(context.getEnvironment());
        }
        return null;
    }

    /**
     * 先尝试从Spring的LocaleResolver中获取区域，以便以自定义的方式获取区域
     *
     * @param request 请求
     * @return 区域
     */
    public static Locale resolveLocale(HttpServletRequest request) {
        Locale locale = null;
        if (request != null) {
            ApplicationContext context = getApplicationContext(request);
            if (context != null) {
                LocaleResolver localeResolver = SpringUtil.getFirstBeanByClass(context, LocaleResolver.class);
                if (localeResolver != null) {
                    locale = localeResolver.resolveLocale(request);
                }
            }
            if (locale == null) {
                locale = request.getLocale();
            }
        }
        if (locale == null) {
            locale = Locale.getDefault();
        }
        return locale;
    }

    public static Locale getLocale() {
        return resolveLocale(SpringWebContext.getRequest());
    }

    public static boolean isResponseBody(HandlerMethod handlerMethod) {
        if (handlerMethod == null) {
            return false;
        }
        return handlerMethod.getReturnType().getParameterType() != ModelAndView.class
                && (handlerMethod.getMethodAnnotation(ResponseBody.class) != null
                || handlerMethod.getBeanType().getAnnotation(RestController.class) != null
                || handlerMethod.getMethodAnnotation(ResponseStream.class) != null);
    }

    public static String getRequestMappingUrl(HandlerMethod handlerMethod) {
        String url = getPath(handlerMethod.getBeanType().getAnnotation(RequestMapping.class));
        if (StringUtils.isBlank(url)) {
            url = Strings.EMPTY;
        }
        String path = getPath(handlerMethod.getMethodAnnotation(RequestMapping.class));
        if (StringUtils.isNotBlank(path)) {
            url += path;
        }
        return NetUtil.standardizeUri(url);
    }

    private static String getPath(RequestMapping requestMapping) {
        if (requestMapping != null) {
            String path = ArrayUtil.get(requestMapping.value(), 0);
            if (path != null) {
                if (path.endsWith(Strings.SLASH)) {
                    path = path.substring(0, path.length() - 1);
                }
                if (!path.startsWith(Strings.SLASH)) {
                    path = Strings.SLASH + path;
                }
                return path;
            }
        }
        return null;
    }

    /**
     * 转换指定结果名为直接重定向的结果名
     *
     * @param result 结果名
     * @return 直接重定向的结果名
     */
    public static String toRedirectResult(String result) {
        return StringUtils.join(REDIRECT_VIEW_NAME_PREFIX, result);
    }
}
